package com.zlzlib.libnetty.msg;


import com.zlzlib.libnetty.listener.NettyClientInterface;
import com.zlzlib.libnetty.util.Util;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by zlz on 2019/11/18.
 * 消息超时自动发送定时器
 */
public class MsgTimeoutTimer<T> extends Timer {

    private final NettyClientInterface<T> imsClient;// im客户端
    private final T msg;// 发送的消息
    private int currentResendCount;// 当前重发次数
    private MsgTimeoutTask task;// 消息发送超时任务

    public MsgTimeoutTimer(NettyClientInterface<T> imsClient, T msg) {
        this.imsClient = imsClient;
        this.msg = msg;
        task = new MsgTimeoutTask();
        this.schedule(task, imsClient.getResendInterval(), imsClient.getResendInterval());
    }

    /**
     * 消息发送超时任务
     */
    private class MsgTimeoutTask extends TimerTask {

        @Override
        public void run() {
            if (imsClient.isClosed()) {
                if (imsClient.getMsgTimeoutTimerManager() != null) {
                    imsClient.getMsgTimeoutTimerManager().remove(imsClient.getDataListener().getMsgId(msg));
                }
                return;
            }
            currentResendCount++;
            if (currentResendCount > imsClient.getResendCount()) {
                // 重发次数大于可重发次数，直接标识为发送失败，并通过消息转发器通知应用层
                try {
                    // 通知应用层消息发送失败
                    T failMsg = imsClient.getDataListener().getSendFailMsg(msg);
                    if (failMsg != null) {
                        imsClient.getMsgDispatcher().receivedMsg(failMsg);
                    }
                } finally {
                    // 从消息发送超时管理器移除该消息
                    if (imsClient.getMsgTimeoutTimerManager() != null) {
                        imsClient.getMsgTimeoutTimerManager().remove(imsClient.getDataListener().getMsgId(msg));
                    }
                    // 执行到这里，认为连接已断开或不稳定，触发重连
                    imsClient.resetConnect();
                    currentResendCount = 0;
                }
            } else {
                // 发送消息，但不再加入超时管理器，达到最大发送失败次数就算了
                sendMsg();
            }
        }
    }

    public void sendMsg() {
        Util.logInfo("正在重发消息，message=" + msg);
        imsClient.sendMsg(msg, false);
    }

    public T getMsg() {
        return msg;
    }

    @Override
    public void cancel() {
        if (task != null) {
            task.cancel();
            task = null;
        }
        super.cancel();
    }

}
